package entity

import (
	"l_net/erro"
	util "l_net/utils"
	"log"
	"net"
	"strings"
)

type UdpListener struct {
	conn     net.PacketConn
	liveList map[string]struct{}
	selfAddr string
}

func NewUdpListener() *UdpListener {
	ip, err := util.GetOutBoundIP()
	log.Println("curr ip addr is : ", ip)
	erro.NetErrShow(err)
	return &UdpListener{
		conn:     nil,
		selfAddr: ip,
	}
}

// 启动监听当前主机的port端口
func (t *UdpListener) Start(port string) {
	broadAddr, err := net.ResolveUDPAddr("udp4", "255.255.255.255:"+port)
	erro.NetErrShow(err)

	conn, err := net.ListenPacket("udp", ":"+port)
	erro.NetErrShow(err)
	//初始化udp监听对象
	t.conn = conn

	msg := NewUpOnlineMsg()
	t.SendMsg(msg, broadAddr) //发送上线信息
	var buf [1024]byte

	defer t.SendMsg(NewShutDown(), broadAddr)
	for {
		//监听消息
		n, addr, err := conn.ReadFrom(buf[:])
		addrStr := strings.Split(addr.String(), ":")[0]
		erro.NetErrShowUdp(err) //不需要退出程序udp而已
		msg, err := Decode(buf[:n])
		erro.NetErrShowUdp(err)
		// msg.OnlineAddr = addr.String()

		//判断消息类型执行对应动作
		switch msg.MsgType {
		case MsgOkUdp:

		case MsgErrUdp:

		case MsgOnline:
			log.Println("addr: ", addrStr, " online")
			if addrStr != t.selfAddr {
				t.liveList[addrStr] = struct{}{}
				log.Println("append addr to map : ", addrStr)
			}
			addrMsg := NewAddrMsg()
			udpaddr, _ := net.ResolveUDPAddr("udp", addr.String())

			t.SendMsg(addrMsg, udpaddr)

		case MsgAddr:
			newList := make(map[string]struct{}, 10)
			if addrStr != t.selfAddr {
				newList[addrStr] = struct{}{}
				log.Println("append addr to map : ", addrStr)
			}
			t.liveList = newList
		case MsgShutDown:
			delete(t.liveList, addrStr)
			log.Println("shut down: ", addrStr)

		}
	}

}

// 发送消息
func (t *UdpListener) SendMsg(msg *MessageUdp, addr *net.UDPAddr) error {
	_, err := t.conn.WriteTo(msg.String(), addr)
	return err
}
